package com.proxy.server.frontend.handler;

import com.proxy.common.constant.ErrorCodeType;
import com.proxy.common.packet.PacketReader;
import com.proxy.common.packet.BinaryPacket;
import com.proxy.common.packet.ErrorPacket;
import com.proxy.common.packet.OkPacket;
import com.proxy.common.utils.CharsetUtil;
import com.proxy.server.frontend.dispatcher.Dispatcher;
import com.proxy.server.context.AppContext;
import com.proxy.server.frontend.FrontendConnection;
import com.proxy.server.frontend.session.Session;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.nio.charset.Charset;

/**
 * 处理一些简单的逻辑转发,核心的再跳转到主分发类来处理。
 * Created by liufish on 16/7/24.
 */
public class FrontendHandler {

    private static final Logger logger = LogManager.getLogger(FrontendHandler.class);

    /**
     * 0 内部线程状态
     */
    public static void comSleep(BinaryPacket bin,Session session) {
        unSupport(bin,session);
    }

    /**
     * 1 关闭连接
     */
    public static void comQuit(BinaryPacket bin, Session session) {
        logger.debug("1 关闭连接");
        session.close();
    }

    /**
     * 2 切换数据库
     */
    public static void comInitDb(BinaryPacket bin,Session session) {
        logger.debug("2 切换数据库");
        PacketReader reader = new PacketReader(bin.body);
        reader.readMove(1);
        String db = reader.readString();
        FrontendConnection connection = session.getFrontendConnection();
        if(db !=null && db.length() > 0 ){
            String schema =  AppContext.getInstance().getFrontendProxy().getSchema();
            if(!db.equalsIgnoreCase(schema)){
                String message = String.format("Access denied for user ' %s' for database ' %s '", connection.getUser(),db);
                ErrorPacket error = new ErrorPacket();
                error.packetId = ++bin.packetId;
                error.errNo = ErrorCodeType.ER_DBACCESS_DENIED_ERROR;
                error.message = message.getBytes();
                connection.getChannel().writeAndFlush(error);
                return;
            }
            connection.setSchema(db);
            connection.getChannel().writeAndFlush(OkPacket.getOk(++bin.packetId));
            return;
        }
        String message = String.format("Access denied for user ' %s' for database ' %s '", connection.getUser(),db);
        ErrorPacket error = new ErrorPacket();
        error.packetId = ++bin.packetId;
        error.errNo = ErrorCodeType.ER_DBACCESS_DENIED_ERROR;
        error.message = message.getBytes();
        connection.getChannel().writeAndFlush(error);
        return;

    }

    /**
     * 3 查询请求
     */
    public static void comQuery(BinaryPacket bin, Session session) {
        logger.debug("3 查询请求");
        //返回到主处理类
        Dispatcher.dispatcherQuery(bin,session);

    }

    /**
     * 4 获取数据表字段信息
     */
    public static void comFieldList(BinaryPacket bin,Session session) {
        unSupport(bin,session);
    }

    /**
     * 5 创建数据库
     */
    public static void comCreateDb(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 6 删除数据库
     */
    public static void comDropDb(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 7清除缓存
     */
    public static void comRefresh(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 8停止服务器
     */
    public static void comShutdown(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 9获取服务器统计信息
     */
    public static void comStatistics(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 10获取当前连接的列表
     */
    public static void comProcessInfo(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 11（内部线程状态）
     */
    public static void comConnect(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 12中断某个连接
     */
    public static void comProcessKill(BinaryPacket bin,Session session) {
        // todo
        logger.debug("12中断某个连接");
    }

    /**
     * 13保存服务器调试信息
     */
    public static void comDebug(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 14测试连通性
     */
    public static void comPing(BinaryPacket bin,Session session) {
        FrontendConnection connection = session.getFrontendConnection();
        connection.write(OkPacket.getOk(++ bin.packetId));
    }

    /**
     * 15（内部线程状态）
     */
    public static void comTime(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 16（内部线程状态）
     */
    public static void comDelayedInsert(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 17重新登陆（不断连接）
     */
    public static void comChangeUser(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 18获取二进制日志信息
     */
    public static void comBinlogDump(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 19获取数据表结构信息
     */
    public static void comTableDump(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 20（内部线程状态）
     */
    public static void comConnectOut(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 21从服务器向主服务器进行注册
     */
    public static void comRegisterSlave(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 22预处理SQL语句
     */
    public static void comStmtPrepare(BinaryPacket bin,Session session) {
        // todo
        logger.debug("22预处理SQL语句");
    }

    /**
     * 23执行预处理语句
     */
    public static void comStmtExecute(BinaryPacket bin,Session session) {
        // todo
        logger.debug("23执行预处理语句");
    }

    /**
     * 24发送BLOB类型的数据
     */
    public static void comStmtSendLongData(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 25销毁预处理语句
     */
    public static void comStmtClose(BinaryPacket bin,Session session) {
        // todo
        logger.debug("25销毁预处理语句");
    }

    /**
     * 26清除预处理语句参数缓存
     */
    public static void comStmtReset(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 27设置语句选项
     */
    public static void comSetOption(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 28获取预处理语句的执行结果
     */
    public static void comStmtFetch(BinaryPacket bin,Session session) {
        unSupport(bin, session);
    }

    /**
     * 不支持类型
     */
    public static void unSupport(BinaryPacket bin,Session session) {
        FrontendConnection connection = session.getFrontendConnection();
        ErrorPacket error = new ErrorPacket();
        error.packetId = bin.packetId+1;
        error.errNo = ErrorCodeType.ER_UNKNOWN_COM_ERROR;
        error.message = "Unknown command".getBytes(Charset.forName(CharsetUtil.getCharset(connection.getCharsetIndex())));
        connection.write(error);
    }
}
